package www.floatwindow.com.floatwindowdemo;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Build;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;

import com.alibaba.idst.nls.NlsClient;
import com.alibaba.idst.nls.internal.protocol.NlsRequest;

import www.floatwindow.com.floatwindowdemo.bean.Recorder;
import www.floatwindow.com.floatwindowdemo.view.AudioRecorderButton;


/**
 * 弹窗辅助类
 * Created by Shawn on 2018/8/30.
 */

public class WindowUtils {
    // 阿里语音
    private NlsClient mNlsClient;
    private NlsRequest mNlsRequest;


    private static final String LOG_TAG = "WindowUtils";
    private Context mContext;
    private View mView = null;
    private View btnView = null;
    private WindowManager mWindowManager = null;
    private Boolean isShown = false;
    private int screenWidth;

    /**
     * 开始点击按下的时间
     */
    private static long startTime;
    /**
     * 结束点击按下的时间
     */
    private static long endTime;

    /**
     * 开始点击按下的坐标X
     */
    private static float mTouchStartX;

    /**
     * 开始点击按下的坐标Y
     */
    private static float mTouchStartY;

    /**
     * 开始移动的坐标X
     */
    private static float mMoveStartX;

    /**
     * 开始移动的坐标Y
     */
    private static float mMoveStartY;


    private static WindowManager.LayoutParams mWmParams;

    public WindowUtils(NlsClient mNlsClient, NlsRequest mNlsRequest) {
        this.mNlsClient = mNlsClient;
        this.mNlsRequest = mNlsRequest;
    }

    /**
     * 显示弹出框
     *
     * @param context
     */
    private void showPopupWindowBtn(final Context context) {
        if (isShown) {
            Log.i(LOG_TAG, "return cause already shown");
            return;
        }
        Log.i(LOG_TAG, "showPopupWindowBtn");
        isShown = true;
        btnView = setBtnView(context);
        mWmParams.format = PixelFormat.TRANSLUCENT;
        // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口
        // 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时，后面的应用图标由不可长按变为可长按
        // 不设置这个flag的话，home页的划屏会有问题
        mWmParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        mWmParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        mWmParams.gravity = Gravity.BOTTOM;
        mWindowManager.addView(btnView, mWmParams);
        Log.i(LOG_TAG, "add BtnView");
    }


    /**
     * 显示弹出框
     *
     * @param context
     */
    void showPopupWindow(final Context context) {
        if (isShown) {
            Log.i(LOG_TAG, "return cause already shown");
            return;
        }
        isShown = true;
        Log.i(LOG_TAG, "showPopupWindow");
        // 获取应用的Context
        mContext = context.getApplicationContext();
        // 获取WindowManager
        mWindowManager = (WindowManager) mContext
                .getSystemService(Context.WINDOW_SERVICE);
        // 获得屏幕宽度
        screenWidth = mWindowManager.getDefaultDisplay().getWidth();
        // 配置window属性
        mWmParams = new WindowManager.LayoutParams();
        // 类型
        /*android7.0不能用TYPE_TOAST*/
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            mWmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        } else {
            /*以下代码块使得android6.0之后的用户不必再去手动开启悬浮窗权限*/
            String packname = context.getPackageName();
            PackageManager pm = context.getPackageManager();
            boolean permission = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.SYSTEM_ALERT_WINDOW", packname));
            if (permission) {
                mWmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            } else {
                mWmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
            }
        }
        // WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
        // 设置flag
        int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
        // | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        // 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE，弹出的View收不到Back键的事件
        mWmParams.flags = flags;
        // 不设置这个弹出框的透明遮罩显示为黑色
        mWmParams.format = PixelFormat.TRANSLUCENT;
        // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口
        // 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时，后面的应用图标由不可长按变为可长按
        // 不设置这个flag的话，home页的划屏会有问题
        mWmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mWmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        //调整悬浮窗显示的停靠位置为左侧置顶
        mWmParams.gravity = Gravity.START | Gravity.TOP;
        mWmParams.x = 0;
        mWmParams.y = 100;
        // 设置布局
        mView = setView(context);
        mWindowManager.addView(mView, mWmParams);
        Log.i(LOG_TAG, "add view");
    }

    /**
     * 隐藏弹出框
     */
    private void hidePopupWindow() {
        Log.i(LOG_TAG, "hidePopupWindow " + isShown + ", " + mView);
        if (isShown && null != mView) {
            Log.i(LOG_TAG, "hidePopupWindow");
            mWindowManager.removeView(mView);
            isShown = false;
        }
    }

    /**
     * 隐藏弹出框
     */
    void hideBtnPopupWindow() {
        Log.i(LOG_TAG, "hideBtnPopupWindow " + isShown + ", " + btnView);
        if (isShown && null != btnView) {
            mWindowManager.removeView(btnView);
            mWmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
            mWmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
            //调整悬浮窗显示的停靠位置为左侧置顶
            mWmParams.gravity = Gravity.START | Gravity.TOP;
            mWindowManager.addView(mView, mWmParams);
        }
    }


    private View setView(final Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.showfloatwindow,
                null);
        ImageView iv_showBtn = view.findViewById(R.id.iv_showBtn);
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                boolean isClick = false;
                boolean clickLocation = false;
                // 获取相对屏幕的坐标，即以屏幕左上角为原点
                // 点击区域的位置
                int rawX = (int) event.getRawX();
                int rawY = (int) event.getRawY();

                int x = (int) event.getX();
                int y = (int) event.getY();
                Rect rect = new Rect();
                boolean clickBoolean = view.getGlobalVisibleRect(rect);
                if (rect.contains(x, y)) {
                    clickLocation = true;
                } else {
                    clickLocation = false;
                }

                //下面的这些事件，跟图标的移动无关，为了区分开拖动和点击事件
                int action = event.getAction();

                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        startTime = System.currentTimeMillis();
                        mTouchStartX = event.getX();
                        mTouchStartY = event.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        //图标移动的逻辑在这里
                        mMoveStartX = event.getX();
                        mMoveStartY = event.getY();

                        mWmParams.x = (int) (rawX - mTouchStartX);
                        mWmParams.y = (int) (rawY - mTouchStartY);

                        mWindowManager.updateViewLayout(view, mWmParams);

                        break;
                    case MotionEvent.ACTION_UP:
                        // 属性动画
//                        ValueAnimator valueAnimator = runAnimator(view, 0, 100);
//                        valueAnimator.start();

                        // 如果移动量大于3才移动
                        if (clickLocation) {
                            if (Math.abs(mTouchStartX - mMoveStartX) > 3
                                    && Math.abs(mTouchStartY - mMoveStartY) > 3) {
                                // 更新浮动窗口位置参数
                                if (rawX <= screenWidth / 2) {
                                    rawX = 0;
                                } else {
                                    rawX = screenWidth;
                                }
                                mWmParams.x = (int) (rawX - mTouchStartX);
                                mWmParams.y = (int) (rawY - mTouchStartY);
                                mWindowManager.updateViewLayout(view, mWmParams);
                                return false;
                            }
                        }

                        endTime = System.currentTimeMillis();
                        //当从点击到弹起小于半秒的时候,则判断为点击,如果超过则不响应点击事件
                        if ((endTime - startTime) > 0.15 * 1000L) {
                            isClick = false;
                        } else {
                            if (clickLocation) {
                                isClick = true;
                            } else {
                                isClick = false;
                            }
                        }
                        break;
                    default:
                        break;
                }
                //响应点击事件
                if (isClick) {
                    hidePopupWindow();
                    showPopupWindowBtn(context);
                }
                return true;
            }
        });
        return view;
    }

    /**
     * 点击悬浮窗之后显示的view
     *
     * @param context
     * @return
     */
    private View setBtnView(final Context context) {
        Log.i(LOG_TAG, "setUp view");
        View view = LayoutInflater.from(context).inflate(R.layout.floatwindow,
                null);
        AudioRecorderButton id_recorder_button = view.findViewById(R.id.id_recorder_button);
        id_recorder_button.setmNlsClient(mNlsClient);
        id_recorder_button.setmNlsRequest(mNlsRequest);
        id_recorder_button.setAudioFinishRecorderListener(new AudioRecorderButton.AudioFinishRecorderListener() {
            @Override
            public void onFinish(float seconds, String filePath) {
                // 开始说话
                //每完成一次录音
//                Recorder recorder = new Recorder(seconds, filePath);
                if (mNlsClient != null) {
                    mNlsClient.stop();
                }
            }
        });

        // 点击窗口外部区域可消除
        // 这点的实现主要将悬浮窗设置为全屏大小，外层有个透明背景，中间一部分视为内容区域
        // 所以点击内容区域外部视为点击悬浮窗外部
        final View popupWindowView = view.findViewById(R.id.popup_window);// 非透明的内容区域
        // 不设置这个事件，无法捕捉到返回监听
        view.setFocusableInTouchMode(true);
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.i(LOG_TAG, "onTouch");
                int x = (int) event.getX();
                int y = (int) event.getY();
                Rect rect = new Rect();
                popupWindowView.getGlobalVisibleRect(rect);
                if (rect.contains(x, y)) {
                    hideBtnPopupWindow();
                }
                Log.i(LOG_TAG, "onTouch : " + x + ", " + y + ", rect: "
                        + rect);
                return false;
            }
        });
        // 点击back键可消除
        view.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                Log.i(LOG_TAG, "OnKey : " + keyCode);
                switch (keyCode) {
                    case KeyEvent.KEYCODE_BACK:
                        hideBtnPopupWindow();
                        return true;
                    case KeyEvent.KEYCODE_HOME:
                        hideBtnPopupWindow();
                        return true;
                    default:
                        return false;
                }
            }
        });
        return view;
    }


    /**
     * 属性动画
     *
     * @param view
     * @param start
     * @param end
     */
    private static ValueAnimator runAnimator(final View view, int start, int end) {
        ValueAnimator animator = ValueAnimator.ofInt(start, end);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                int value = (Integer) valueAnimator.getAnimatedValue();
                ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
                layoutParams.width = value;
                view.setLayoutParams(layoutParams);
            }
        });
        animator.setCurrentPlayTime(1000);
        return animator;
    }
}
